package hu.bme.aut.consulttime.server.file;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Date;
import java.util.Hashtable;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.io.FileUtils;

import gwtupload.server.UploadAction;
import gwtupload.server.exceptions.UploadActionException;
import gwtupload.shared.UConsts;
import hu.bme.aut.consulttime.server.email.EmailProvider;
import hu.bme.aut.consulttime.server.entities.Log;
import hu.bme.aut.consulttime.server.entityservices.EntityManagerFactoryWrapper;

public class LogFileUploadServlet extends UploadAction {
	private static final long serialVersionUID = 666L;

	Hashtable<String, String> receivedContentTypes = new Hashtable<String, String>();
	/**
	 * Maintain a list with received files and their content types. 
	 */
	Hashtable<String, File> receivedFiles = new Hashtable<String, File>();

	public static final EntityManager entityManager() {
		return EntityManagerFactoryWrapper.get().createEntityManager();
	}

	/**
	 * Override executeAction to save the received files in a custom place
	 * and delete this items from session.  
	 */
	@Override
	public String executeAction(HttpServletRequest request, List<FileItem> sessionFiles) throws UploadActionException {
		
		Log log = null;
		
		for (FileItem item : sessionFiles) {
			if (false == item.isFormField()) {
				try {
					/// Create a new file based on the remote file name in the client
					// String saveName = item.getName().replaceAll("[\\\\/><\\|\\s\"'{}()\\[\\]]+", "_");
					// File file =new File("/tmp/" + saveName);

					/// Create a temporary file placed in /tmp (only works in unix)
					// File file = File.createTempFile("upload-", ".bin", new File("/tmp"));

					/// Create a temporary file placed in the default system temp folder
					File file = File.createTempFile("temp-", "-" + item.getName());
					item.write(file);

					String logIdString = item.getFieldName().substring(0, item.getFieldName().indexOf('-'));
					System.out.println(logIdString);
					long logId = Long.valueOf(logIdString);

					EntityManager em = entityManager();
					EntityTransaction tx = em.getTransaction();
					
					try {
						tx.begin();
						log = em.find(Log.class, logId);
						log.setAttachedFile(FileUtils.readFileToByteArray(file));
						log.setAttachedFileName(item.getName());
						log.setDate(new Date());
						em.merge(log);
						tx.commit();
					} 
					catch (Throwable t) {
						tx.rollback();
						t.printStackTrace();
					} 
					finally {
						em.close();
					}
					
					try {
						
						if (log.getToDo().getTutor().isEmailNotification()) {
							
							String emailAddress = log.getToDo().getTutor().getEmail();
							String subject = "New log file attachment on ConsultTime!";
							String body = "Project: " + log.getToDo().getTeam().getProject().getTitle() + "\n";
							body = body + "Team: " + log.getToDo().getTeam().getName() + "\n";
							body = body + "Student: " + log.getToDo().getStudent().getFirstName() + " " + log.getToDo().getStudent().getLastName() + " (" + log.getToDo().getStudent().getUserName() + ")\n\n";
							body = body + "To-do:\n";
							body = body + "Date: " + log.getToDo().getDate().toString() + "\n";
							body = body + "Title: " + log.getToDo().getTitle() + "\n";
							body = body + "Week: " + String.valueOf(log.getToDo().getWeek()) + "\n\n";
							body = body + "Log:\n";
							body = body + "Date: " + log.getDate().toString() + "\n";
							body = body + "File name: " + log.getAttachedFileName();
							
							EmailProvider.sendEmail(emailAddress, subject, body);
						}
					} catch (Throwable t) {
					}

					/// Save a list with the received files
					receivedFiles.put(item.getFieldName(), file);
					receivedContentTypes.put(item.getFieldName(), item.getContentType());

					/// Send a customized message to the client.
					//response += "File saved as " + file.getAbsolutePath();

				} catch (Exception e) {
					//throw new UploadActionException(e);
					e.printStackTrace();
				}
			}
		}

		/// Remove files from session because we have a copy of them
		removeSessionFileItems(request);

		/// Send your customized message to the client.
		return String.valueOf(log.getToDo().getTodoId());
	}

	/**
	 * Get the content of an uploaded file.
	 */
	@Override
	public void getUploadedFile(HttpServletRequest request, HttpServletResponse response) throws IOException {
		String fieldName = request.getParameter(UConsts.PARAM_SHOW);
		File f = receivedFiles.get(fieldName);
		if (f != null) {
			response.setContentType(receivedContentTypes.get(fieldName));
			FileInputStream is = new FileInputStream(f);
			copyFromInputStreamToOutputStream(is, response.getOutputStream());
		} else {
			renderXmlResponse(request, response, XML_ERROR_ITEM_NOT_FOUND);
		}
	}

	/**
	 * Remove a file when the user sends a delete request.
	 */
	@Override
	public void removeItem(HttpServletRequest request, String fieldName)  throws UploadActionException {
		File file = receivedFiles.get(fieldName);
		receivedFiles.remove(fieldName);
		receivedContentTypes.remove(fieldName);
		if (file != null) {
			file.delete();
		}
	}
}
